home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 2.1 / Amiga Developer CD v2.1.iso / Reference / DevCon / Washington_1988 / DevCon88.3 / Printer / src / Xerox_4020 / render.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  9.9 KB  |  363 lines

  1. /*
  2.     Xerox-4020 driver.
  3.     David Berezowski - October/87.
  4.  
  5.   Copyright (c) 1988 Commodore-Amiga, Inc.
  6.  
  7.   Executables based on this information may be used in software
  8.   for Commodore Amiga computers.  All other rights reserved.
  9.  
  10.   This information is provided "as is"; no warranties are made.
  11.   All use is at your own risk, and no liability or responsibility is assumed.
  12. */
  13.  
  14.  
  15. #include <exec/types.h>
  16. #include <exec/nodes.h>
  17. #include <exec/lists.h>
  18. #include <exec/memory.h>
  19. #include "../printer/printer.h"
  20. #include "../printer/prtbase.h"
  21.  
  22. #define NUMSTARTCMD    7    /* # of cmd bytes before binary data */
  23. #define NUMENDCMD    0    /* # of cmd bytes after binary data */
  24. #define NUMTOTALCMD     (NUMSTARTCMD + NUMENDCMD)    /* total of above */
  25. #define NUMLFCMD    9    /* # of cmd bytes for linefeed */
  26. #define MAXCOLORBUFS    16    /* max # of color buffers */
  27.  
  28. #define RLEMAX        136
  29. #define RLENUMSTARTCMD    3    /* # of cmd bytes before binary data */
  30. #define RLENUMENDCMD    1    /* # of cmd bytes after binary data */
  31. #define RLENUMTOTALCMD     (RLENUMSTARTCMD + RLENUMENDCMD)    /* total of above */
  32. #define RLESAFETY    10    /* extra room for overwrites */
  33.  
  34. #define PMODE        15    /* index into StartBuf for print mode */
  35. #define STARTLEN    16    /* length of start buffer */
  36.  
  37. extern UBYTE MargBuf[];
  38.  
  39. Render(ct, x, y, status)
  40. long ct, x, y, status;
  41. {
  42.     extern void *AllocMem(), FreeMem();
  43.     extern struct PrinterData *PD;
  44.     extern struct PrinterExtendedData *PED;
  45.  
  46.     static UWORD RowSize, ColorSize, BufSize, TotalBufSize, dataoffset;
  47.     static UWORD colors[MAXCOLORBUFS]; /* color indexes */
  48.     static UWORD color_order[] =
  49.         {0, 1, 2, 3, 8, 9, 10, 11, 4, 5, 6, 7, 12, 13, 14, 15};
  50.     static UWORD huns, tens, ones; /* used to program buffer size */
  51.     static UWORD NumColorBufs; /* actually # of color buffers */
  52.     /*
  53.         00-02    \033F0        set 10 cpi
  54.         03-07    \033l05\r    set left margin to .5 inches
  55.         09-12    \033r95\r    set right margin to 9.5 inches
  56.         13-15    \033we        select standard (e) or
  57.                     enhanced (f) graphics mode.
  58.     */
  59.     static UBYTE stdmode, StartBuf[STARTLEN] =
  60.         "\033F0\033l05\r\033r95\r\033we";
  61.     UBYTE *ptr, *ptrstart, *ptr2, *ptr2start;
  62.     int i, err;
  63.  
  64.     static UWORD RLEBufSize, rledataoffset;
  65.     static UBYTE *RLEBuf;
  66.     UBYTE *rleptrstart, *rleptr, *rleptrmark, rledata;
  67.     int rlesize, rlecount, j;
  68.  
  69.     switch(status) {
  70.         case 0 : /* Master Initialization */
  71.             /*
  72.                 ct    - pointer to IODRPReq structure.
  73.                 x    - width of printed picture in pixels.
  74.                 y    - height of printed picture in pixels.
  75.             */
  76.             /* calc # of bytes of row data */
  77.             RowSize = (x + 7) / 8;
  78.             /* size of each color buf */
  79.             ColorSize = RowSize + NUMTOTALCMD;
  80.             huns = RowSize / 100;
  81.             tens = (RowSize - huns * 100) / 10;
  82.             ones = RowSize % 10;
  83.             if (PD->pd_Preferences.PrintShade == SHADE_COLOR) {
  84.                 NumColorBufs = MAXCOLORBUFS;
  85.             }
  86.             else {
  87.                 NumColorBufs = 4;
  88.             }
  89.             BufSize = ColorSize * NumColorBufs + NUMLFCMD;
  90.             TotalBufSize = BufSize * 2;
  91.             RLEBufSize = BufSize + RLESAFETY;
  92.             TotalBufSize += RLEBufSize * 2;
  93.             /*
  94.                 My color order:        B, Y, M, C
  95.                 Xerox's color order:    B, M, Y, C
  96.             */
  97.             for (i=0; i<NumColorBufs; i++) {
  98.                 colors[color_order[i]] = ColorSize * i;
  99.             }
  100.             PD->pd_PrintBuf = AllocMem(TotalBufSize, MEMF_PUBLIC);
  101.             if (PD->pd_PrintBuf == NULL) {
  102.                 err = PDERR_BUFFERMEMORY; /* no mem */
  103.             }
  104.             else {
  105.                 dataoffset = NUMSTARTCMD;
  106.                 err = (*(PD->pd_PWrite))(StartBuf, STARTLEN);
  107.                 RLEBuf = &PD->pd_PrintBuf[BufSize * 2];
  108.                 rledataoffset = RLENUMSTARTCMD;
  109.             }
  110.             break;
  111.  
  112.         case 1 : /* Scale, Dither and Render */
  113.             /*
  114.                 ct    - pointer to PrtInfo structure.
  115.                 x    - 0.
  116.                 y    - row # (0 to Height - 1).
  117.             */
  118.             Transfer(ct, y, &PD->pd_PrintBuf[dataoffset], colors);
  119.             err = PDERR_NOERR; /* all ok */
  120.             break;
  121.  
  122.         case 2 : /* Dump Buffer to Printer */
  123.             /*
  124.                 ct    - 0.
  125.                 x    - 0.
  126.                 y    - # of rows sent (1 to NumRows).
  127.             */
  128.             /* Run-Length Encode (rle) the data */
  129.             rleptrstart = rleptr =
  130.                 &RLEBuf[rledataoffset - RLENUMSTARTCMD];
  131.             /* ptr to data */
  132.             ptrstart = &PD->pd_PrintBuf[dataoffset];
  133.             for (ct=0; ct<NumColorBufs;
  134.                 ct++, ptrstart += ColorSize) {
  135.                 /* save start posn for this color */
  136.                 rleptrmark = rleptr;
  137.                 *rleptr++ = 27; /* rle start cmd */
  138.                 *rleptr++ = 'h';
  139.                 *rleptr++ = ct | '0'; /* color code */
  140.                 ptr = ptrstart; /* get ptr to bytes to rle */
  141.                 j = RowSize - 1; /* # of bytes left to rle */
  142.                 do {
  143.                     /* first do repeating bytes */
  144.                     /* get goal (repeating) byte */
  145.                     rledata = *ptr++;
  146.                     /* this many repetitions left to go*/
  147.                     i = RLEMAX - 1;
  148.                     /* while repeating and not too many
  149.                         and more to do */
  150.                     while (*ptr == rledata && i > 0 &&
  151.                         j > 0) {
  152.                         i--; /* one more rle byte */
  153.                         /* advance ptr to next byte */
  154.                         ptr++;
  155.                         /* one less byte to look at */
  156.                         j--;
  157.                     }
  158.                     /* calc repeating byte count */
  159.                     if ((rlecount = RLEMAX - i) == 1) {
  160.                         /* if only 1 then no repeat */
  161.                         rlecount = 0;
  162.                     }
  163.                     else {
  164.                         /* dont forget the goal byte */
  165.                         j--;
  166.                     }
  167.                     /* if there was repeat data */
  168.                     if (rlecount != 0) {
  169.                         /* save repeat count */
  170.                         *rleptr++ = rlecount;
  171.                         /* save repeat byte */
  172.                         *rleptr++ = rledata;
  173.                         /* get non-repeat goal byte */
  174.                         rledata = *ptr++;
  175.                     }
  176.                     /* now do non-repeating data */
  177.                     /* no non-repeating bytes yet */
  178.                     rlecount = 0;
  179.                     if (*ptr != rledata && j >= 0) {
  180.                         /* non-repeat data follows */
  181.                         *rleptr++ = 0x00;
  182.                     }
  183.                     /* while non-repeating and more to do */
  184.                     while (*ptr != rledata && j >= 0) {
  185.                         /* save byte */
  186.                         *rleptr++ = rledata;
  187.                         /* if byte same as terminator */
  188.                         if (rledata == 0xfe) {
  189.                             /* save byte (again) */
  190.                             *rleptr++ = rledata;
  191.                         }
  192.                         /* one more non-repeat byte */
  193.                         rlecount++;
  194.                         /* get goal byte */
  195.                         rledata = *ptr++;
  196.                         /* one less byte to look at */
  197.                         j--;
  198.                     }
  199.                     if (rlecount != 0) {
  200.                         /* end of non-repeating bytes */
  201.                         *rleptr++ = 0xfe;
  202.                     }
  203.                     if (j > 0) { /* if more data to do */
  204.                         /* set ptr back to start
  205.                             of repeat bytes */
  206.                         ptr--;
  207.                     }
  208.                     if (rleptr - rleptrstart > BufSize) {
  209.                         /* abort: too many rle bytes */
  210.                         break;
  211.                     }
  212.                 } while (j > 0); /* while more bytes to rle */
  213.  
  214.                 /* if didnt abort && no non-repeating data */
  215.                 if (j < 1 && rlecount == 0) {
  216.                     /* check for trailing white space */
  217.                     /* line ends in trailing 0 */
  218.                     if (*(rleptr - 1) == 0x00) {
  219.                         /* ptr back to repeat count */
  220.                         rleptr -= 2;
  221.                     }
  222.                 }
  223.                 /* if line is just the cmd bytes */
  224.                 /* line null */
  225.                 if (rleptr - rleptrmark == RLENUMSTARTCMD) {
  226.                     /* reset ptr to start */
  227.                     rleptr = rleptrmark;
  228.                 }
  229.                 else {
  230.                     *rleptr++ = 0xff; /* end of rle line */
  231.                 }
  232.             }
  233.             i = rleptr - rleptrstart; /* calc size of rlebuf */
  234.             /* if rle data is more send non-rle data */
  235.             if (i > BufSize) {
  236.                 ptrstart = &PD->pd_PrintBuf[dataoffset -
  237.                     NUMSTARTCMD];
  238.                 ptr = ptrstart + BufSize - NUMLFCMD;
  239.                 /* if standard print mode and any black
  240.                     in this micro-line */
  241.                 if (stdmode && *(ptrstart + 2) < '4') {
  242.                     *ptr++ = 27;
  243.                     *ptr++ = 'k';
  244.                     *ptr++ = '0';    /* cr */
  245.                     *ptr++ = 27;
  246.                     *ptr++ = 'w';
  247.                     *ptr++ = 'B';    /* repeat black */
  248.                 }
  249.                 *ptr++ = 27;
  250.                 *ptr++ = 'k';
  251.                 *ptr++ = '1';        /* cr/lf */
  252.                 err = (*(PD->pd_PWrite))
  253.                     (ptrstart, ptr - ptrstart);
  254.             }
  255.             else { /* send rle data */
  256.                 /* if any black in this micro-line */
  257.                 if (rleptr - rleptrstart > 0 &&
  258.                     *(rleptrstart + 2) < '4') {
  259.                     *rleptr++ = 27;
  260.                     *rleptr++ = 'k';
  261.                     *rleptr++ = '0'; /* cr */
  262.                     *rleptr++ = 27;
  263.                     *rleptr++ = 'w';
  264.                     *rleptr++ = 'B'; /* repeat black */
  265.                 }
  266.                 *rleptr++ = 27;
  267.                 *rleptr++ = 'k';
  268.                 *rleptr++ = '1';    /* cr/lf */
  269.                 i = rleptr - rleptrstart; /* size of rlebuf */
  270.                 err = (*(PD->pd_PWrite))(rleptrstart, i);
  271.             }
  272.             if (err == PDERR_NOERR) {
  273.                 dataoffset = (dataoffset == NUMSTARTCMD ?
  274.                     BufSize : 0) + NUMSTARTCMD;
  275.                 rledataoffset = (rledataoffset ==
  276.                     RLENUMSTARTCMD ? RLEBufSize : 0) +
  277.                     RLENUMSTARTCMD;
  278.             }
  279.             break;
  280.  
  281.         case 3 : /* Clear and Init Buffer */
  282.             /*
  283.                 ct    - 0.
  284.                 x    - 0.
  285.                 y    - 0.
  286.             */
  287.             ptr = &PD->pd_PrintBuf[dataoffset];
  288.             i = BufSize - NUMTOTALCMD - NUMLFCMD;
  289.             do {
  290.                 *ptr++ = 0;
  291.             } while (--i);
  292.             for (ct=0; ct<NumColorBufs; ct++) {
  293.                 ptr = &PD->pd_PrintBuf[dataoffset -
  294.                     NUMSTARTCMD + ct * ColorSize];
  295.                 *ptr++ = 27;
  296.                 *ptr++ = 'g';
  297.                 *ptr++ = ct + '0';    /* color */
  298.                 *ptr++ = huns | '0';
  299.                 *ptr++ = tens | '0';
  300.                 *ptr++ = ones | '0';    /* printout width */
  301.                 *ptr = ',';        /* terminator */
  302.             }
  303.             err = PDERR_NOERR; /* all ok */
  304.             break;
  305.  
  306.         case 4 : /* Close Down */
  307.             /*
  308.                 ct    - error code.
  309.                 x    - io_Special flag from IODRPReq.
  310.                 y    - 0.
  311.             */
  312.             /* if user did not cancel print */
  313.             if (ct != PDERR_CANCEL) {
  314.                 /* restore preferences pitch and margins */
  315.                 i = CalcMarg(PD->pd_Preferences.PrintLeftMargin
  316.                     , PD->pd_Preferences.PrintRightMargin);
  317.                 err = (*(PD->pd_PWrite))(MargBuf, i);
  318.             }
  319.             /* wait for both buffers to empty */
  320.             (*(PD->pd_PBothReady))();
  321.             if (PD->pd_PrintBuf != NULL) {
  322.                 FreeMem(PD->pd_PrintBuf, TotalBufSize);
  323.             }
  324.             err = PDERR_NOERR; /* all ok */
  325.             break;
  326.  
  327.         case 5 : /* Pre-Master Initialization */
  328.             /*
  329.                 ct    - 0 or pointer to IODRPReq structure.
  330.                 x    - io_Special flag from IODRPReq.
  331.                 y    - 0.
  332.             */
  333.             StartBuf[PMODE - 1] = 'w';
  334.             if ((x & SPECIAL_DENSITYMASK) < SPECIAL_DENSITY2) {
  335.                 /* standard graphics mode */
  336.                 StartBuf[PMODE] = 'e';
  337.                 stdmode = 1;
  338.             }
  339.             else {
  340.                 /* enhanced graphics mode */
  341.                 StartBuf[PMODE] = 'f';
  342.                 stdmode = 0;
  343.             }
  344.             PED->ped_MaxColumns = PD->pd_Preferences.PaperSize ==
  345.                 W_TRACTOR ? 90 : 80;
  346.             /* def is 80 chars (8.0 in.),
  347.                 W_TRACTOR is 90 chars (9.0 in.) */
  348.             PED->ped_MaxXDots = (PED->ped_XDotsInch *
  349.                 PED->ped_MaxColumns) / 10;
  350.             /*
  351.             The manual says that the printer has 1088 dots BUT I
  352.             could never get more than 1080 out of it.  This kludge
  353.             is here as '121 * 90 / 10 = 1089' which is > 1080.
  354.             */
  355.             if (PED->ped_MaxXDots > 1080) {
  356.                  PED->ped_MaxXDots = 1080;
  357.             }
  358.             err = PDERR_NOERR; /* all ok */
  359.             break;
  360.     }
  361.     return(err);
  362. }
  363.